/**
 * 
 */
package blms.system.user;

import static blms.system.util.Validator.isBlankOrNull;

import java.io.File;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;

import blms.system.exception.UnknownAttribute;
import blms.system.exception.UserDoesNotExistException;
import blms.system.exception.restrictions.RestrictionException;
import blms.system.util.BLMSMessages;
import blms.system.util.ReflectionHelper;
import blms.system.util.Validator;

/**
 * @author thiago
 *
 */
public class UserEntry {

	private Map<String, User> users = new HashMap<String, User>();
	 
	/**
	 * @param firstName
	 * @param lastName
	 * @param homePhone
	 * @param workPhone
	 * @param cellPhone
	 * @param email
	 * @param picture
	 * @return
	 * @throws RestrictionException
	 */
	public String createUser(String firstName, String lastName, String homePhone, String workPhone,
								String cellPhone, String email, File picture) throws RestrictionException {
		
		
		validateUser(firstName,lastName,email,homePhone,workPhone,cellPhone);
		
		User user = new User(firstName, lastName, homePhone, workPhone, cellPhone, email, picture);
		
		users.put(user.getID(), user);
		return user.getID();
	}
	
	private void validateUser(String firstName, String lastName, String email, String homePhone,
										String workPhone, String cellPhone) throws RestrictionException {
	
		if (containsUser(email)) throw new RestrictionException(BLMSMessages.USER_WITH_THIS_MAIL_EXISTS_MESSAGE);
		
		if (isBlankOrNull(firstName) || isBlankOrNull(lastName) || isBlankOrNull(email)) {
			
			String message = (isBlankOrNull(firstName)) ? "first name" : "";
			if(isBlankOrNull(lastName)) {
				message = (message.equals("")) ? message + "last name": message + ", "+ "last name";
			}
			if(isBlankOrNull(email)) {
				message = (message.equals("")) ? message + "email": message + ", "+ "email";
			}
			
			throw new RestrictionException(BLMSMessages.REQUIRED_DATA_MESSAGE+message);
		}
		
		if (isBlankOrNull(homePhone) && isBlankOrNull(workPhone) && isBlankOrNull(cellPhone))
			throw new RestrictionException(BLMSMessages.NEED_AT_LEAST_ONE_PHONE_MESSAGE);
	}
	
	/**
	 * @param id
	 * @return
	 */
	public boolean containsUser(String id) {
		return this.users.containsKey(id);
	}
	
	/**
	 * @param id
	 * @return
	 * @throws UserDoesNotExistException
	 */
	public User getUser(String id) throws UserDoesNotExistException {
		
		if (!containsUser(id)) throw new UserDoesNotExistException(BLMSMessages.UNKNOWN_USER_MESSAGE);
		
		return users.get(id);
	}
	
	/**
	 * @param id
	 * @param attribute
	 * @param value
	 * @throws UserDoesNotExistException
	 * @throws UnknownAttribute
	 * @throws RestrictionException
	 */
	public void changeUserAttribute(String id, String attribute, String value) throws UserDoesNotExistException,
																						UnknownAttribute, RestrictionException {

		User user = getUser(id);
		
		if (Validator.isBlankOrNull(attribute)) throw new RestrictionException(BLMSMessages.MUST_PROVIDE_ATTRIBUTE_MESSAGE);
		
		if (attribute.equals("picture")) {
			new ReflectionHelper().setAttribute(user, attribute, (value != null) ? new File(value) : value);
		}else {
			
			if (attribute.equals("email")) {
				User userAux = getUser(id);
				if (this.users.keySet().contains(value) && !userAux.getEmail().equals(value)) {
					throw new RestrictionException(BLMSMessages.USER_WITH_THIS_MAIL_EXISTS_MESSAGE);
				}
			}
			
			new ReflectionHelper().setAttribute(user, attribute, value);
		}
	}
	
	/**
	 * @param id
	 * @param attribute
	 * @return
	 * @throws UserDoesNotExistException
	 * @throws UnknownAttribute
	 */
	public String getUserAttribute(String id, String attribute) throws UserDoesNotExistException, UnknownAttribute {
		return new ReflectionHelper().getAttribute(getUser(id), attribute);
	}
	
	/**
	 * @param lastName
	 * @return
	 * @throws UserDoesNotExistException
	 */
	public List<String> findUserByLastName(String lastName) throws UserDoesNotExistException {
		
		List<String> returnValue = new LinkedList<String>();

		//TODO: REFACTOR, EMCAPSULAR NUM METODO DA CLASSE UTIL, CODIGO REPETIDO EM LEAGUE
		for (User user : this.users.values()) {
		
			java.util.regex.Pattern p = java.util.regex.Pattern.compile(lastName, java.util.regex.Pattern.CASE_INSENSITIVE);
			Matcher m = p.matcher(user.getLastName());
			if (m.matches()) {
				returnValue.add(user.getLastName());
			}
		}
		
		if (returnValue.isEmpty()) throw new UserDoesNotExistException(BLMSMessages.COULD_NOT_FIND_USER_MESSAGE+" "+lastName);
		return returnValue;
	}
	
	/**
	 * @param id
	 * @throws RestrictionException
	 * @throws UserDoesNotExistException
	 */
	public void remove(String id) throws RestrictionException, UserDoesNotExistException {
		
		if(!containsUser(id)) throw new UserDoesNotExistException();
		this.users.remove(id);
	}
	
	/**
	 * Removes all users from the system.
	 */
	public void removeAllUsers() {
		this.users = new HashMap<String, User>();
	}
}
